package com.byx.imclientutil.utils;

import androidx.annotation.NonNull;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * NioEventLoopGroupUtil
 *
 * @author Superb
 * @date 2021/2/9 18:01
 */
public class NioEventLoopGroupUtil {
    final AtomicInteger atomicInteger = new AtomicInteger(1);

    private ExecutorService bossPool;
    private ExecutorService workerPool;

    private final BossThreadPoolFactory bossThreadPoolFactory=new BossThreadPoolFactory("boss线程");
    private final BossThreadPoolFactory workerThreadPoolFactory=new BossThreadPoolFactory("worker线程");

    /**
     * 初始化boss线程池
     */
    public synchronized void initBossLoopGroup() {
        destroyBossLoopGroup();
        bossPool = new ThreadPoolExecutor(1, 1,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(),bossThreadPoolFactory);
    }

    /**
     * 初始化work线程池
     */
    public synchronized void initWorkLoopGroup() {
        destroyWorkLoopGroup();
        workerPool=new ThreadPoolExecutor(1, 1,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(),workerThreadPoolFactory);
    }

    /**
     * 执行boss任务
     *
     * @param r
     */
    public void execBossTask(Runnable r) {
        if (bossPool == null) {
            initBossLoopGroup();
        }
        bossPool.execute(r);
    }

    /**
     * 执行work任务
     *
     * @param r
     */
    public void execWorkTask(Runnable r) {
        if (workerPool == null) {
            initWorkLoopGroup();
        }
        workerPool.execute(r);
    }

    /**
     * 释放boss线程池
     */
    public synchronized void destroyBossLoopGroup() {
        if (bossPool != null) {
            try {
                bossPool.shutdownNow();
            } catch (Throwable t) {
                t.printStackTrace();
            } finally {
                bossPool = null;
            }
        }
    }

    /**
     * 释放work线程池
     */
    public synchronized void destroyWorkLoopGroup() {
        if (workerPool != null) {
            try {
                workerPool.shutdownNow();
            } catch (Throwable t) {
                t.printStackTrace();
            } finally {
                workerPool = null;
            }
        }
    }

    /**
     * 释放所有线程池
     */
    public synchronized void destroy() {
        destroyBossLoopGroup();
        destroyWorkLoopGroup();
    }

    class BossThreadPoolFactory implements ThreadFactory {
        private String name;

        public BossThreadPoolFactory(String name) {
            this.name = name;
        }

        /**
         * Constructs a new {@code Thread}.  Implementations may also initialize
         * priority, name, daemon status, {@code ThreadGroup}, etc.
         *
         * @param r a runnable to be executed by new thread instance
         * @return constructed thread, or {@code null} if the request to
         * create a thread is rejected
         */
        @Override
        public Thread newThread(Runnable r) {
            Thread t=new Thread(r,name+atomicInteger.incrementAndGet());
            t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
                @Override
                public void uncaughtException(@NonNull Thread t, @NonNull Throwable e) {
                    System.out.println("线程 "+t.getId()+" "+t.getName()+" 发生未捕获异常...");
                }
            });
            return t;
        }
    }
}
